package org.gdstash.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;

public class GDMsgFormatter {
    private static String resLanguage;
    private static String language;
    private static String country;
    public static Locale locale;
    private static MessageFormat msgFormatter;
    public static ResourceBundle rbGD;
    public static ResourceBundle rbMsg;
    public static ResourceBundle rbUI;
    public static ResourceBundle rbHTML;

    public static void readHTMLResourceBundle() throws IOException {
        if (GDMsgFormatter.rbHTML != null) {
            return;
        }
        final String fnHTML = GDConstants.USER_DIR + GDConstants.FILE_SEPARATOR + "HTMLTags.properties";
        try (final InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fnHTML)), GDConstants.CHARSET_PROPERTIES)) {
            GDMsgFormatter.rbHTML = new PropertyResourceBundle(reader);
        } catch (IOException ex) {
            throw ex;
        }
    }

    public static void setGDLocale(final String language) throws IOException {
        if (language == null) {
            return;
        }
        if (GDMsgFormatter.resLanguage != null && GDMsgFormatter.resLanguage.equals(language)) {
            return;
        }
        GDMsgFormatter.resLanguage = language;
        final String fnGD = GDConstants.USER_DIR + GDConstants.FILE_SEPARATOR + "GrimDawn_" + language + ".properties";
        final String fnUI = GDConstants.USER_DIR + GDConstants.FILE_SEPARATOR + "UI_" + language + ".properties";
        final String fnMsg = GDConstants.USER_DIR + GDConstants.FILE_SEPARATOR + "Messages_" + language + ".properties";
        try (final InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fnGD)), GDConstants.CHARSET_PROPERTIES)) {
            GDMsgFormatter.rbGD = new PropertyResourceBundle(reader);
        } catch (IOException ex) {
            throw ex;
        }
        try (final InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fnUI)), GDConstants.CHARSET_PROPERTIES)) {
            GDMsgFormatter.rbUI = new PropertyResourceBundle(reader);
        } catch (IOException ex) {
            throw ex;
        }
        try (final InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fnMsg)), GDConstants.CHARSET_PROPERTIES)) {
            GDMsgFormatter.rbMsg = new PropertyResourceBundle(reader);
        } catch (IOException ex) {
            throw ex;
        }
        GDMsgFormatter.language = getString(GDMsgFormatter.rbUI, "LANGUAGE");
        GDMsgFormatter.country = getString(GDMsgFormatter.rbUI, "COUNTRY");
        GDMsgFormatter.locale = new Locale(GDMsgFormatter.language, GDMsgFormatter.country);
        GDMsgFormatter.msgFormatter = new MessageFormat("", GDMsgFormatter.locale);
        Locale.setDefault(Locale.Category.DISPLAY, GDMsgFormatter.locale);
    }

    public static String format_alt(final ResourceBundle bundle, final String tag, final Object[] args) {
        final String s = bundle.getString(tag);
        return format(s, args);
    }

    public static String format(final String text, final Object[] args) {
        String s = text;
        if (s == null) {
            return s;
        }
        if (args == null) {
            return s;
        }
        if (args.length == 0) {
            return s;
        }
        int pos1 = 0;
        int pos2 = 0;
        pos1 = s.indexOf("{");
        if (pos1 == -1) {
            return s;
        }
        String start = "";
        String rest = s;
        String pattern = null;
        String format1 = null;
        String format2 = null;
        String index = null;
        String value = null;
        while (pos1 != -1) {
            pos2 = rest.indexOf("}");
            if (pos2 == -1) {
                start += rest;
                rest = "";
            } else {
                start += rest.substring(0, pos1);
                pattern = rest.substring(pos1 + 1, pos2);
                rest = rest.substring(pos2 + 1);
                pos1 = pattern.indexOf(",");
                if (pos1 == -1) {
                    index = pattern;
                    format1 = null;
                } else {
                    index = pattern.substring(0, pos1).trim();
                    format1 = pattern.substring(pos1 + 1).trim();
                }
                int idx = -1;
                try {
                    idx = Integer.parseInt(index);
                } catch (NumberFormatException ex) {
                    idx = -1;
                }
                if (idx == -1) {
                    value = index;
                } else if (format1 == null) {
                    try {
                        value = (String) args[idx];
                    } catch (ArrayIndexOutOfBoundsException ex2) {
                        value = index;
                    }
                } else {
                    pos1 = format1.indexOf(",");
                    if (pos1 == -1) {
                        format2 = null;
                    } else {
                        format2 = format1.substring(pos1 + 1).trim();
                        format1 = format1.substring(0, pos1).trim();
                    }
                    if (format1.equals("number")) {
                        if (format2 == null) {
                            value = (String) args[idx];
                        } else {
                            double d = 0.0;
                            boolean found = false;
                            if (args[idx].getClass().equals(Double.class)) {
                                d = (double) args[idx];
                                found = true;
                            }
                            if (args[idx].getClass().equals(Float.class)) {
                                final float f = (float) args[idx];
                                d = f;
                                found = true;
                            }
                            if (args[idx].getClass().equals(Integer.class)) {
                                final int i = (int) args[idx];
                                d = i;
                                found = true;
                            }
                            if (!found) {
                                value = (String) args[idx];
                            } else if (format2.equals("integer")) {
                                value = Integer.toString((int) d);
                            } else {
                                try {
                                    final DecimalFormat df = new DecimalFormat(format2);
                                    value = df.format(d);
                                } catch (IllegalArgumentException ex3) {
                                    value = index;
                                }
                            }
                        }
                    } else {
                        value = index;
                    }
                }
                start += value;
            }
            pos1 = rest.indexOf("{");
        }
        s = start;
        if (s != null) {
            final ByteBuffer buffer = StandardCharsets.UTF_8.encode(s);
            final String utf8 = s = StandardCharsets.UTF_8.decode(buffer).toString();
        }
        return s;
    }

    public static String format(final ResourceBundle bundle, final String tag, final Object[] args) {
        String s = null;
        try {
            GDMsgFormatter.msgFormatter.applyPattern(bundle.getString(tag));
            s = GDMsgFormatter.msgFormatter.format(args);
            if (s != null) {
                final ByteBuffer buffer = StandardCharsets.UTF_8.encode(s);
                final String utf8 = s = StandardCharsets.UTF_8.decode(buffer).toString();
            }
        } catch (MissingResourceException ex) {
            final Object[] errargs = {tag};
            final String msg = format(GDMsgFormatter.rbMsg, "ERR_TAG_UNKNOWN", errargs);
            GDMsgLogger.addError(msg);
            return "";
        } catch (IllegalArgumentException ex2) {
            final Object[] errargs = {tag};
            final String msg = format(GDMsgFormatter.rbMsg, "ERR_PATTERN_WRONG", errargs);
            GDMsgLogger.addError(msg);
            return "";
        } catch (StringIndexOutOfBoundsException ex3) {
            final Object[] errargs = {tag};
            final String msg = format(GDMsgFormatter.rbMsg, "ERR_PATTERN_WRONG", errargs);
            GDMsgLogger.addError(msg);
            return "";
        }
        return s;
    }

    public static String getString(final ResourceBundle bundle, final String tag) {
        String s = null;
        try {
            s = bundle.getString(tag);
            if (s != null) {
                final ByteBuffer buffer = StandardCharsets.UTF_8.encode(s);
                s = StandardCharsets.UTF_8.decode(buffer).toString();
            }
        } catch (MissingResourceException ex) {
            final Object[] errargs = {tag};
            final String msg = format(GDMsgFormatter.rbMsg, "ERR_TAG_UNKNOWN", errargs);
            GDMsgLogger.addError(msg);
            return "";
        }
        return s;
    }
}
